package ru.amse.tsyganov.jumleditor.view.activepoints;

import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.GC;

import ru.amse.tsyganov.jumleditor.commands.Command;
import ru.amse.tsyganov.jumleditor.commands.CommandFactory;
import ru.amse.tsyganov.jumleditor.graphicaleditor.Coordinates;
import ru.amse.tsyganov.jumleditor.model.ActivityGraph;
import ru.amse.tsyganov.jumleditor.model.State;
import ru.amse.tsyganov.jumleditor.model.Transition;
import ru.amse.tsyganov.jumleditor.view.ConnectionPoint;
import ru.amse.tsyganov.jumleditor.view.lines.Line;
import ru.amse.tsyganov.jumleditor.view.lines.SimpleLine;
import ru.amse.tsyganov.jumleditor.view.pref.Colors;
import ru.amse.tsyganov.jumleditor.view.pref.Cursors;
import ru.amse.tsyganov.jumleditor.view.repr.ActivityGraphView;
import ru.amse.tsyganov.jumleditor.view.repr.StateView;
import ru.amse.tsyganov.jumleditor.view.repr.TransitionView;

public abstract class TransitionActivePoint extends ActivePoint {
	
	private final boolean sourceMoving;
	
	public TransitionActivePoint(boolean sourceMoving) {
		this.sourceMoving = sourceMoving;
	}
	
	public abstract TransitionView<? extends Transition> getTransitionView();
	
	public abstract ActivityGraphView<? extends ActivityGraph> getContainer();
	
	@Override
	public final Cursor getCursor() {
		return Cursors.getCursorSizeAll();
	}

	@Override
	public final void paintTempResult(GC gc, Coordinates coordinates) {
		assert gc != null;
		
		gc.setForeground(Colors.getGrayColor());
		gc.setBackground(Colors.getGrayColor());
		
		ConnectionPoint fixedPoint = sourceMoving ? 
			getTransitionView().getTargetConnectionPoint() :
				getTransitionView().getSourceConnectionPoint();
			
		StateView<? extends State> stateView = 
			getContainer().getStateView( 
					getTemporaryActivePointX(), 
					getTemporaryActivePointY());
		
		gc.setBackground(Colors.getBlackColor());
		
		if (stateView == null) {
			TransitionView.drawArrowedLine(gc, coordinates,
					new SimpleLine(
					fixedPoint.getCpX(), 
					fixedPoint.getCpY(),
					getTemporaryActivePointX(), 
					getTemporaryActivePointY()), !sourceMoving);	
		} else {
			ConnectionPoint currentPoint = stateView.getNearestConnectionPoint(
					getTemporaryActivePointX(), 
					getTemporaryActivePointY());
			Line[] lines = sourceMoving ?
					TransitionView.getBrokenLine(currentPoint, fixedPoint) :
						TransitionView.getBrokenLine(fixedPoint, currentPoint);
			TransitionView.drawArrowedLine(gc, coordinates, lines);
		}
		
	}

	@Override
	public final Command createCommandForAction() {
		StateView<? extends State> newStateView = 
			getContainer().getStateView( 
					getTemporaryActivePointX(), 
					getTemporaryActivePointY());
		
		if (newStateView == null) {
			return null;
		}
		
		ConnectionPoint newSourceConnectionPoint = (sourceMoving) ? 
			newStateView.getNearestConnectionPoint(getTemporaryActivePointX(), getTemporaryActivePointY()) :
					getTransitionView().getSourceConnectionPoint();
				
		ConnectionPoint newTargetConnectionPoint = (!sourceMoving) ? 
				newStateView.getNearestConnectionPoint(getTemporaryActivePointX(), getTemporaryActivePointY()) :
					getTransitionView().getTargetConnectionPoint();
				
		if (newSourceConnectionPoint.getContainer() == 
			newTargetConnectionPoint.getContainer()) {
			
			return null;
		}
				
		if (newSourceConnectionPoint == getTransitionView().getSourceConnectionPoint() &&
			newTargetConnectionPoint == getTransitionView().getTargetConnectionPoint()) {
			
			getTransitionView().initBrokenLine();
			return null;
		}
		
		return CommandFactory.createMoveTransitionCommand(
				getTransitionView(), 
				newSourceConnectionPoint, newTargetConnectionPoint);
	}

	public boolean isSourceMoving() {
		return sourceMoving;
	}

}
